home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / music / eked-m1.zoo / src / gm / wind_man.c < prev   
C/C++ Source or Header  |  1995-02-19  |  26KB  |  881 lines

  1. /*
  2.  *  EKED-M1 : Editor for Korg M1 synth; wind_man.c : window manager
  3.  *  Copyright (C) 1995 Steven M. Eker (Steven.Eker@brunel.ac.uk)
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <stddef.h>
  21. #include <osbind.h>        /* for Vsync() */
  22. #include <gemfast.h>
  23. #include <aesbind.h>
  24. #include <vdibind.h>
  25. #include "gem_man.h"
  26.  
  27. #define WM_HASH(h)    (((unsigned) (h)) % MAX_WINDOWS)
  28. #define LSB_COPY(d, s)    ((d) ^ (((s) ^ (d)) & 1))
  29. #define LSB_NEQ(n, m)    (((n) ^ (m)) & 1)
  30. #define MAKE_EVEN(n)    ((n) & ~1)
  31.  
  32. typedef struct window_struct {
  33.   int aes_handle;        /* aes handle for window */
  34.   int parts;            /* window part flags */
  35.   int con_w;            /* width of contents */
  36.   int con_h;            /* height of contents */
  37.   int x_offset;            /* x offset of visible portion of contents */
  38.   int y_offset;            /* y offset of visible portion of contents */
  39.   int x_scroll;            /* number of pixels for hscroll step */
  40.   int y_scroll;            /* number of pixels for vscroll step */
  41.   DISP_FUNC_PTR display;    /* pointer to display code for contents */
  42.   ACT_FUNC_PTR action;        /* pointer to action code for window */
  43.   long usr_val;            /* user value */
  44.   struct window_struct *above;    /* pointer to window above us */
  45.   struct window_struct *below;    /* pointer to window below us */
  46. } WINDOW;
  47.  
  48. static WINDOW wm_table[MAX_WINDOWS];
  49. static WINDOW *top_win;
  50. static WINDOW *bot_win;
  51. static GRECT used_stack[MAX_WINDOWS];
  52. static int used_top = -1;
  53. static int roll_handle;
  54. static int quiting = FALSE;
  55.  
  56. static WINDOW *get_window(int h);
  57. static void wm_resized(int handle, GRECT *area);
  58. static void wm_hscroll(int handle, int offset, WINDOW *w, GRECT *area);
  59. static void wm_vscroll(int handle, int offset, WINDOW *w, GRECT *area);
  60. static void roll_redraw(OBJECT *tree, int ob, GRECT *area);
  61.  
  62. #define PUSH(w)                                \
  63. (                                    \
  64.   (w)->above = NULL,                            \
  65.   (w)->below = top_win,                            \
  66.   top_win ? (top_win->above = (w)) : (bot_win = (w)),            \
  67.   top_win = (w)                                \
  68. )
  69.  
  70. #define YANK(w)                                \
  71. (                                    \
  72.   ((w)->above ? ((w)->above->below = (w)->below) :            \
  73.                 (top_win = (w)->below)),                \
  74.   ((w)->below ? ((w)->below->above = (w)->above) :            \
  75.                 (bot_win = (w)->above))                    \
  76. )
  77.  
  78. /*
  79.  *    Basic window management functions
  80.  */
  81.  
  82. static WINDOW *get_window(int h)
  83. {
  84.   WINDOW *start = wm_table + WM_HASH(h), *w = start;
  85.  
  86.   while(w->aes_handle != h){
  87.     if(++w == wm_table + MAX_WINDOWS)
  88.       w = wm_table;
  89.     if(w == start)
  90. /*
  91.  *    wind_find() gave us someone elses window
  92.  *    or window has closed since message was generated.
  93.  */
  94.       return NULL;
  95.   }
  96.   return w;
  97. }
  98.  
  99. void wm_getdata(int handle, int *x_pos, int *y_pos, long *usr_val)
  100. {
  101.   WINDOW *w = get_window(handle);
  102.   GRECT rect;
  103.  
  104.   wind_get(handle, WF_WORKXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
  105.   *x_pos = rect.g_x - w->x_offset;
  106.   *y_pos = rect.g_y - w->y_offset;
  107.   *usr_val = w->usr_val;
  108. }
  109.  
  110. void wm_send_redraw(int handle, GRECT *area)
  111. {
  112.   static int msg[] = {WM_REDRAW, 0, 0, 0, 0, 0, 0, 0};
  113.  
  114.   msg[1] = gl_apid;
  115.   msg[3] = handle;
  116.   if(area == NULL)
  117.     wind_get(handle, WF_WORKXYWH, msg + 4, msg + 5, msg + 6, msg + 7);
  118.   else
  119.     *((GRECT *) (msg + 4)) = *area;
  120.   appl_write(gl_apid, (int) sizeof(msg), msg);
  121. }
  122.  
  123. void wm_send_user(int handle, long object)
  124. {
  125.   WINDOW *w = get_window(handle);
  126.   GRECT rect;
  127.  
  128.   wind_get(handle, WF_WORKXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
  129.   (*(w->action))(w->aes_handle, E_USER, (void *) object,
  130.     rect.g_x - w->x_offset, rect.g_y - w->y_offset, w->usr_val);
  131. }
  132.  
  133. void wm_exit()
  134. {
  135.   WINDOW *w;
  136.  
  137.   quiting = TRUE;
  138.   for(w = wm_table; w < wm_table + MAX_WINDOWS; w++){
  139.     if(w->aes_handle != 0)
  140.       wm_closed(w->aes_handle);
  141.   }
  142. }
  143.  
  144. int wm_open(int parts, GRECT *init, char *title,
  145.             int con_w, int con_h, int x_scroll, int y_scroll,
  146.             DISP_FUNC_PTR display, ACT_FUNC_PTR action, long usr_val)
  147. {
  148.   WINDOW *start, *w;
  149.   GRECT max, work;
  150.   int h;
  151.  
  152.   wind_calc(WC_BORDER, parts, 0, 0, con_w, con_h,
  153.             &max.g_x, &max.g_y, &max.g_w, &max.g_h);
  154.   if(max.g_w > desk.g_w)
  155.     max.g_w = desk.g_w - LSB_NEQ(max.g_w, desk.g_w);
  156.   if(max.g_h > desk.g_h)
  157.     max.g_h = desk.g_h - LSB_NEQ(max.g_h, desk.g_h);
  158.   max.g_x = desk.g_x;
  159.   max.g_y = desk.g_y;
  160.   h = wind_create(parts, max.g_x, max.g_y, max.g_w, max.g_h);
  161.   if(h < 0)
  162.     return OUT_OF_WINDOWS;
  163.   start = wm_table + WM_HASH(h);
  164.   for(w = start; w->aes_handle != 0;){
  165.     if(++w == wm_table + MAX_WINDOWS)
  166.       w = wm_table;
  167.     if(w == start){
  168.       wind_delete(h);
  169.       return OUT_OF_WINDOWS;
  170.     }
  171.   }
  172.   if(init != NULL){
  173.     init->g_x = MAKE_EVEN(init->g_x);
  174.     init->g_y = MAKE_EVEN(init->g_y);
  175.     if(init->g_w > max.g_w)
  176.       init->g_w = max.g_w;
  177.     else
  178.       init->g_w += LSB_NEQ(con_w, init->g_w);
  179.     if(init->g_h > max.g_h)
  180.       init->g_h = max.g_h;
  181.     else
  182.       init->g_h += LSB_NEQ(con_h, init->g_h);
  183.   }
  184.   else if(used_top >= 0){
  185.     init = &(used_stack[used_top--]);
  186.     if(init->g_w > max.g_w || !(parts & HSLIDE))
  187.       init->g_w = max.g_w;
  188.     if(init->g_h > max.g_h || !(parts & VSLIDE))
  189.       init->g_h = max.g_h;
  190.   }
  191.   else
  192.     init = &max;
  193.   w->aes_handle = h;
  194.   w->parts = parts;
  195.   w->con_w = con_w;
  196.   w->con_h = con_h;
  197.   w->x_scroll = x_scroll;
  198.   w->y_scroll = y_scroll;
  199.   w->x_offset = 0;
  200.   w->y_offset = 0;
  201.   w->usr_val = usr_val;
  202.   w->display = display;
  203.   w->action = action;
  204.   PUSH(w);
  205.   wind_set(h, WF_NAME, title, 0, 0);
  206.   if(parts & (HSLIDE | VSLIDE)){
  207.     wind_calc(WC_WORK, parts, init->g_x, init->g_y, init->g_w, init->g_h,
  208.               &work.g_x, &work.g_y, &work.g_w, &work.g_h);
  209.     if(parts & HSLIDE){
  210.       wind_set(h, WF_HSLSIZE, (int) RDIV(1000L * work.g_w, con_w), 0, 0, 0);
  211.       wind_set(h, WF_HSLIDE, 0, 0, 0, 0);
  212.     }
  213.     if(parts & VSLIDE){
  214.       wind_set(h, WF_VSLSIZE, (int) RDIV(1000L * work.g_h, con_h), 0, 0, 0);
  215.       wind_set(h, WF_VSLIDE, 0, 0, 0, 0);
  216.     }
  217.   }
  218.   wind_open(h, init->g_x, init->g_y, init->g_w, init->g_h);
  219.   return h;
  220. }
  221.  
  222. void wm_closed(int h)
  223. {
  224.   WINDOW *w = get_window(h);
  225.  
  226.   (void) (*(w->action))(w->aes_handle, E_CLEANUP, (void *) NULL,
  227.                         0, 0, w->usr_val);
  228.   if(used_top < MAX_WINDOWS - 1){
  229.     used_top++;
  230.     wind_get(h, WF_CURRXYWH,
  231.              &(used_stack[used_top].g_x), &(used_stack[used_top].g_y),
  232.              &(used_stack[used_top].g_w), &(used_stack[used_top].g_h));
  233.   }
  234.   wind_close(h);
  235.   wind_delete(h);
  236.   YANK(w);
  237.   w->aes_handle = 0;
  238. /*
  239.  *    Avoid build up of stale messages from successive closes.
  240.  */
  241.   wm_flush(!quiting);
  242. }
  243.  
  244. void wm_redraw(int handle, GRECT *area)
  245. {
  246.   WINDOW *w = get_window(handle);
  247.   DISP_FUNC_PTR display = w->display;
  248.   GRECT rect;
  249.   int x_pos, y_pos;
  250.  
  251.   if(w == NULL)
  252.     return;    /* processing stale redraw message */
  253.   wind_get(handle, WF_WORKXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
  254.   x_pos = rect.g_x - w->x_offset;
  255.   y_pos = rect.g_y - w->y_offset;
  256.   wind_update(BEG_UPDATE);
  257.   graf_mouse(M_OFF, 0L);
  258.   wind_get(handle, WF_FIRSTXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
  259.   while(rect.g_w != 0 && rect.g_h != 0){
  260.     if(intersect(area, &rect))
  261.       (*display)(x_pos, y_pos, &rect, w->usr_val);
  262.     wind_get(handle, WF_NEXTXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
  263.   }
  264.   graf_mouse(M_ON, 0L);
  265.   wind_update(END_UPDATE);
  266. }
  267.  
  268. void wm_moved(int handle, GRECT *area)
  269. {
  270.   wind_set(handle, WF_CURRXYWH, LSB_COPY(are